//
//  CrushView.h
//  FruitCrush
//
//  Created by gaoyu on 15/7/19.
//
//

#ifndef __FruitCrush__CrushView__
#define __FruitCrush__CrushView__

#include "cocos2d.h"
USING_NS_CC;

#define CRUSH_VIEW_WIDTH   320
#define CRUSH_VIEW_HEIGHT  225

typedef std::function<void(Ref*)> crushViewCallback;
typedef std::function<void(Ref*)> crushViewBadStateCallback;
typedef std::function<void(Ref*)> crushViewCoverCloseCallback;

class CrushUnitSprite;
class BadStateUnitSprite;

class CrushView : public cocos2d::Layer
{
public:
	CC_SYNTHESIZE(int, m_bombNum, BombNum);
    CC_SYNTHESIZE_READONLY(int, m_crushType, CrushType);
    CC_SYNTHESIZE_READONLY(int, m_suckNum, SuckNum);
    CC_SYNTHESIZE_READONLY(int, m_combosNum, CombosNum);
    CrushView();
    ~CrushView();
    CREATE_FUNC(CrushView);
    virtual bool init() override;
    virtual void update(float dt) override;
    virtual bool onTouchBegan(Touch *touch, Event *unused) override;
    virtual void onTouchMoved(Touch *touch, Event *unused) override;
    void setCallback(const crushViewCallback& callback);
    void setBadCallback(const crushViewBadStateCallback& callback);
    void setCoverCallback(const crushViewCoverCloseCallback& callback);
    void setPause(bool pause);
    void initMatrixBad(bool* data);
    void initMatrixBadUp(bool* data);
    void initMatrix(bool* data);
    void bossCreateJellys();
    void initMatrixProtectCover(bool* data);
    void initMatrixBlank(bool* data);
protected:
    // callback
    crushViewCallback _callback;
    crushViewBadStateCallback _badCallback;
    crushViewCoverCloseCallback _coverCallback;
private:
    SpriteBatchNode *spriteSheet;
    CrushUnitSprite **m_matrix;
    int m_width;
    int m_height;
    // for rapid count position
    float m_matrixLeftBottomX;
    float m_matrixLeftBottomY;
    bool m_isTouchEnable;// is need to deal with touch event
    CrushUnitSprite *m_srcSushi;
    CrushUnitSprite *m_destSushi;
    CrushUnitSprite *m_allTargetSushi;
    bool m_isAnimationing;
    bool m_isNeedFillVacancies;
    bool m_movingVertical;
    bool m_isPause;
    float m_badStateLastTime;
    //add for bad state
    SpriteBatchNode *spriteSheetBad;
    BadStateUnitSprite **m_matrix_bad;
    SpriteBatchNode *spriteSheetBadUp;
    BadStateUnitSprite **m_matrix_bad_up;
    bool m_needCreateJelly;
    SpriteBatchNode *spriteSheetProtectCover;
    BadStateUnitSprite **m_matrix_protect_cover;
    bool m_isCoverNeedClose;
    SpriteBatchNode *spriteSheetBlank;
    BadStateUnitSprite **m_matrix_blank;
    
    //void initMatrix();
    void createAndDropSushi(int row, int col);
    Point positionOfItem(int row, int col);
    bool checkAndRemoveChain();
    void getColChain(CrushUnitSprite *sushi, std::list<CrushUnitSprite *> &chainList);
    void getRowChain(CrushUnitSprite *sushi, std::list<CrushUnitSprite *> &chainList);
    bool removeSushi();
    void actionEndCallback(Node *node);
    void explodeSushi(CrushUnitSprite *sushi);
    void fillVacancies();
    CrushUnitSprite *sushiOfPoint(Point *point);
    bool swapSushi();
    void markRemove(CrushUnitSprite *sushi);
    void explodeSpecialH(Point point);
    void explodeSpecialV(Point point);
    void explodeSpecialO(Point point);
    //add
    Vec2 touchLocationFix(Vec2 location);
    void createBadState(int row, int col);
    int getBadStateNum();
    void suckCheckUpdate(float dt);
    void createBadUpState(int row, int col);
    bool isHandByMonster(int row, int col);
    void createJelly(int row, int col);
    void checkJellyEatUnit();
    __Array* getAllCanEatJelly();
    bool isJellyHasEatTarget(int row, int col);
    void JellyEatTarget(int row, int col);
    void jellyEatEndCallback(Node *node);
    void explodeJelly(int row,int col);
    void crushJellyCheck(int row, int col);
    void bossCreateJelly(int row, int col);
    void createAndDropBomb(int row, int col);
    bool isThereHasBomb();
    void bombDropOut(int row, int col);
    bool bombCreateCheck(int row, int col);
    void createProtectCover(int row, int col);
    void crushCoverCheck(int row, int col);
    void coverCloseCheck();
    void createBlank(int row, int col);
    int getBlankNum(int newRow, int col,int row);
    void circleMarkRemove(std::list<CrushUnitSprite *>  &colChainList,
    		                         std::list<CrushUnitSprite *>  &rowChainList);
    bool checkHasCircle(std::list<CrushUnitSprite *> &colChainList,
                                   std::list<CrushUnitSprite *> &rowChainList);
    void afterChainRemoveDo(CrushUnitSprite *sushi);
    
};

#endif /* defined(__FruitCrush__CrushView__) */
